# views.py - 智能修复版本
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import AllowAny, IsAdminUser, IsAuthenticated
from django.shortcuts import get_object_or_404
from django.db import transaction
from .utils import topic_sampling
from .serializers import LogistQuestionSerializer
from .models import LogistQuestion, ChoiceOption
import uuid
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAdminUser, IsAuthenticated
from .models import LogistQuestion, ChoiceOption, ExamSession, ExamAnswer
from .serializers import LogistQuestionSerializer, ExamSessionSerializer, ExamAnswerSerializer
import csv
import io


class GenerateLogistExamAPIView(APIView):
    """GET /api/exams/exam/?total=10 返回抽题结果"""

    # 禁用认证要求
    permission_classes = [AllowAny]

    def get(self, request):
        try:
            total = int(request.query_params.get('total', 10))
        except ValueError:
            return Response({'error': 'total 必须为整数'}, status=status.HTTP_400_BAD_REQUEST)

        # 智能获取：只包含数据库中有数据的题型
        topic_ratios = {}
        available_topics = []

        # 预定义的理想比例
        ideal_ratios = {
            '逻辑思维题': 2,
            '逻辑推理题': 2,
            '类比推理题': 1,
            '图形推理题': 2,
            '数学运算': 2,
            '阅读理解': 1,
        }

        # 检查每个类型在数据库中是否有数据
        for topic, ratio in ideal_ratios.items():
            count = LogistQuestion.objects.filter(topic=topic).count()
            if (count > 0):
                topic_ratios[topic] = ratio
                available_topics.append(f"{topic}({count}个)")

        # 如果没有任何可用题目
        if not topic_ratios:
            return Response({
                'error': '数据库中没有可用的题目',
                'suggestion': '请先导入题目数据：python manage.py import_questions LogistQuestions.xlsx'
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            questions = topic_sampling(topic_ratios, total)
        except ValueError as e:
            return Response({
                'error': str(e),
                'available_topics': available_topics,
                'suggestion': '尝试减少题目数量或导入更多题目数据'
            }, status=status.HTTP_400_BAD_REQUEST)

        # 在context中加入request，序列化器才能生成完整的图片URL
        serializer = LogistQuestionSerializer(questions, many=True, context={'request': request})
        return Response({'questions': serializer.data})


class QuestionListAPIView(APIView):
    """
    GET /api/exams/questions/ 返回所有题目
    POST /api/exams/questions/ 创建新题目
    """

    # 禁用认证要求
    permission_classes = [AllowAny]

    def get(self, request):
        """获取所有题目"""
        # 获取筛选参数
        question_type = request.query_params.get('question_type')
        topic = request.query_params.get('topic')

        # 构建查询条件
        queryset = LogistQuestion.objects.all()
        
        if question_type:
            queryset = queryset.filter(question_type=question_type)
        
        if topic:
            queryset = queryset.filter(topic=topic)

        # 按ID排序
        questions = queryset.order_by('-id')

        # 序列化数据
        serializer = LogistQuestionSerializer(questions, many=True, context={'request': request})

        return Response({'questions': serializer.data})

    def post(self, request):
        """创建新题目"""
        try:
            with transaction.atomic():
                # 从请求数据中提取题目信息
                question_data = {
                    'question_id': request.data.get('question_id', f"Q{uuid.uuid4().hex[:8]}"),
                    'stem': request.data.get('stem', ''),
                    'question_type': request.data.get('question_type', 1),
                    'topic': request.data.get('topic', '逻辑思维题'),
                    'score': request.data.get('score', 2),
                    'answer': request.data.get('answer', ''),
                    'suggested_time': request.data.get('suggested_time', 10)
                }

                # 验证必填字段
                if not question_data['stem']:
                    return Response({'error': '题目内容不能为空'}, status=status.HTTP_400_BAD_REQUEST)

                # 创建题目
                question = LogistQuestion.objects.create(**question_data)

                # 如果是选择题，创建选项
                if question.question_type == 1:
                    options_data = request.data.get('options', [])
                    if not options_data:
                        return Response({'error': '选择题必须包含选项'}, status=status.HTTP_400_BAD_REQUEST)

                    for option_data in options_data:
                        ChoiceOption.objects.create(
                            question=question,
                            label=option_data.get('label', 'A'),
                            content=option_data.get('content', ''),
                        )

                # 返回创建的题目
                serializer = LogistQuestionSerializer(question, context={'request': request})
                return Response({
                    'message': '题目创建成功',
                    'question': serializer.data
                }, status=status.HTTP_201_CREATED)

        except Exception as e:
            return Response({
                'error': f'创建题目失败: {str(e)}'
            }, status=status.HTTP_400_BAD_REQUEST)


class QuestionDetailAPIView(APIView):
    """
    GET /api/exams/questions/{id}/ 获取单个题目详情
    PUT /api/exams/questions/{id}/ 更新题目
    DELETE /api/exams/questions/{id}/ 删除题目
    """

    # 禁用认证要求
    permission_classes = [AllowAny]

    def get_object(self, pk):
        """获取题目对象"""
        return get_object_or_404(LogistQuestion, pk=pk)

    def get(self, request, pk):
        """获取单个题目详情"""
        question = self.get_object(pk)
        serializer = LogistQuestionSerializer(question, context={'request': request})
        return Response(serializer.data)

    def put(self, request, pk):
        """更新题目"""
        try:
            with transaction.atomic():
                question = self.get_object(pk)

                # 更新题目基本信息
                question.stem = request.data.get('stem', question.stem)
                question.question_type = request.data.get('question_type', question.question_type)
                question.topic = request.data.get('topic', question.topic)
                question.score = request.data.get('score', question.score)
                question.answer = request.data.get('answer', question.answer)
                question.suggested_time = request.data.get('suggested_time', question.suggested_time)
                
                question.save()

                # 如果是选择题，更新选项
                if question.question_type == 1:
                    options_data = request.data.get('options', [])
                    
                    # 删除现有选项
                    question.options.all().delete()
                    
                    # 创建新选项
                    for option_data in options_data:
                        ChoiceOption.objects.create(
                            question=question,
                            label=option_data.get('label', 'A'),
                            content=option_data.get('content', ''),
                        )

                # 返回更新后的题目
                serializer = LogistQuestionSerializer(question, context={'request': request})
                return Response({
                    'message': '题目更新成功',
                    'question': serializer.data
                })

        except Exception as e:
            return Response({
                'error': f'更新题目失败: {str(e)}'
            }, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        """删除题目"""
        try:
            question = self.get_object(pk)
            question_id = question.question_id
            question.delete()
            
            return Response({
                'message': f'题目 {question_id} 删除成功'
            }, status=status.HTTP_204_NO_CONTENT)

        except Exception as e:
            return Response({
                'error': f'删除题目失败: {str(e)}'
            }, status=status.HTTP_400_BAD_REQUEST)


class LogistQuestionViewSet(viewsets.ModelViewSet):
    """
    HR功能：笔试题库的增删改查与批量上传
    """
    queryset = LogistQuestion.objects.prefetch_related('options').order_by('question_id')
    serializer_class = LogistQuestionSerializer
    permission_classes = [IsAuthenticated] # 假设所有登录用户都能看，但只有HR能操作，可以用更细的权限控制

    @action(detail=False, methods=['post'], permission_classes=[IsAuthenticated]) # 暂定为 IsAuthenticated，可改为IsHRUser
    def bulk_upload(self, request, *args, **kwargs):
        """
        从CSV文件批量上传题目。
        CSV格式:
        question_id,stem,question_type,topic,score,answer,suggested_time,option_a,option_b,option_c,option_d
        - question_type: 1 (选择题), 2 (填空题)
        - 如果是填空题，option列留空
        """
        csv_file = request.FILES.get('file')
        if not csv_file:
            return Response({"error": "请上传CSV文件"}, status=status.HTTP_400_BAD_REQUEST)

        try:
            decoded_file = csv_file.read().decode('utf-8')
            io_string = io.StringIO(decoded_file)
            reader = csv.DictReader(io_string)
            
            created_count = 0
            errors = []

            for row in reader:
                try:
                    question_type = int(row.get('question_type'))
                    
                    # 创建或更新问题
                    question, created = LogistQuestion.objects.update_or_create(
                        question_id=row.get('question_id'),
                        defaults={
                            'stem': row.get('stem'),
                            'question_type': question_type,
                            'topic': row.get('topic'),
                            'score': int(row.get('score')),
                            'answer': row.get('answer'),
                            'suggested_time': int(row.get('suggested_time')) if row.get('suggested_time') else None,
                        }
                    )
                    
                    # 如果是选择题，创建选项
                    if question_type == 1:
                        # 先删除旧选项，再创建新选项
                        question.options.all().delete()
                        options_data = {
                            'A': row.get('option_a'),
                            'B': row.get('option_b'),
                            'C': row.get('option_c'),
                            'D': row.get('option_d'),
                        }
                        for label, content in options_data.items():
                            if content: # 只创建有内容的选项
                                ChoiceOption.objects.create(
                                    question=question,
                                    label=label,
                                    content=content
                                )
                    
                    if created:
                        created_count += 1

                except Exception as e:
                    errors.append(f"Row {reader.line_num} with ID {row.get('question_id', 'N/A')}: {str(e)}")

            if errors:
                return Response({
                    "message": "部分数据导入失败",
                    "created_count": created_count,
                    "errors": errors
                }, status=status.HTTP_400_BAD_REQUEST)

            return Response({
                "message": "批量上传成功",
                "created_count": created_count,
            }, status=status.HTTP_201_CREATED)

        except Exception as e:
            return Response({"error": f"处理文件时出错: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class ExamSessionAPIView(APIView):
    """
    考试会话管理
    POST /api/exams/sessions/ - 创建新会话
    GET /api/exams/sessions/{session_id}/ - 获取会话详情
    """
    permission_classes = [AllowAny]

    def post(self, request):
        """创建新的考试会话"""
        session_id = f"EXAM_{uuid.uuid4().hex[:8]}"
        session = ExamSession.objects.create(session_id=session_id)
        serializer = ExamSessionSerializer(session)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def get(self, request, session_id=None):
        """获取会话详情"""
        if not session_id:
            return Response({'error': '需要提供session_id'}, status=status.HTTP_400_BAD_REQUEST)
        
        session = get_object_or_404(ExamSession, session_id=session_id)
        serializer = ExamSessionSerializer(session)
        return Response(serializer.data)

class ExamAnswerAPIView(APIView):
    """
    答题和评分
    POST /api/exams/sessions/{session_id}/answer/ - 提交答案
    POST /api/exams/sessions/{session_id}/complete/ - 完成考试并计算总分
    """
    permission_classes = [AllowAny]

    def post(self, request, session_id):
        """提交答案"""
        session = get_object_or_404(ExamSession, session_id=session_id)
        
        if session.is_completed:
            return Response({'error': '该考试会话已完成'}, status=status.HTTP_400_BAD_REQUEST)

        # 获取请求数据
        question_id = request.data.get('question_id')
        user_answer = request.data.get('answer')

        if not question_id or not user_answer:
            return Response({'error': '需要提供question_id和answer'}, status=status.HTTP_400_BAD_REQUEST)

        # 获取题目
        question = get_object_or_404(LogistQuestion, question_id=question_id)

        # 创建或更新答案
        answer, created = ExamAnswer.objects.update_or_create(
            session=session,
            question=question,
            defaults={'user_answer': user_answer}
        )

        # 检查答案
        answer.check_answer()
        
        serializer = ExamAnswerSerializer(answer)
        return Response(serializer.data)

    @action(detail=True, methods=['post'])
    def complete(self, request, session_id):
        """完成考试并计算总分"""
        session = get_object_or_404(ExamSession, session_id=session_id)
        
        if session.is_completed:
            return Response({'error': '该考试会话已完成'}, status=status.HTTP_400_BAD_REQUEST)

        # 计算总分
        total_score = session.calculate_total_score()
        session.is_completed = True
        session.save()

        serializer = ExamSessionSerializer(session)
        return Response({
            'message': '考试已完成',
            'total_score': total_score,
            'session': serializer.data
        })